/***************************************************************************
 *   Copyright (C) 2007 by Grzegorz Latarowski   *
 *   g.latarowski@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "roieditor.h"



// ===========================================================================
//                              GRoiEditor
// ===========================================================================


// --------------------- GRoiEditor::GRoiEditor() ----------------------------
GRoiEditor::GRoiEditor( QObject * pParent )
	: QGraphicsScene( pParent )
{
		// clear manip items
	_pStartMarker = NULL;
	_pEndMarker   = NULL;
	_pRoi         = NULL;

	_userVisibility = false;
	_visible        = false;
	
		// setup scene
	this->setItemIndexMethod( QGraphicsScene::NoIndex );
}
// ---------------------------------------------------------------------------


// --------------------- GRoiEditor::drawBackground() ------------------------
void GRoiEditor::drawBackground( QPainter * pPainter, const QRectF &rect )
{
	if( !pPainter ) return;
		// fill hole scene with black
	pPainter->fillRect( rect, QBrush( Qt::black ) );
	QRectF sceneRect = this->sceneRect();
	pPainter->drawPixmap( sceneRect.toRect(), _pixmap );
}
// ---------------------------------------------------------------------------


// ---------------------- GRoiEditor::setPixmap() ----------------------------
void GRoiEditor::setPixmap( const QPixmap & pixmap )
{
		// set widgets pixmap
	_pixmap = pixmap;
	
		// get _pixmaps sizes
	double w = (double) _pixmap.width();
	double h = (double) _pixmap.height();
	
		// set scene rect in the _pixmap's size, if nessesery,
		// setup roi and markers to defaults 
	QRectF newSceneRect( 0, 0, w, h );
	if( newSceneRect != this->sceneRect() )
	{
		this->setSceneRect( newSceneRect );
		setDefaultRegions();
	}

		// class scene to update backGround
	this->setBackgroundBrush( QBrush() );
}
// ---------------------------------------------------------------------------


// -------------------- GRoiEditor::showTools() ------------------------------
void GRoiEditor::showTools( bool show )
{
	_userVisibility = true;
	_visible        = show;
	
	if ( _pRoi ) _pRoi->setVisible( show );
	if ( _pStartMarker ) _pStartMarker->setVisible( show );
	if ( _pEndMarker ) _pEndMarker->setVisible( show );
}
// ---------------------------------------------------------------------------
	

// ------------------------ GRoiEditor::setDefaultRegions() ------------------
void GRoiEditor::setDefaultRegions()
{
		// get _pixmaps sizes
	double w = (double) _pixmap.width();
	double h = (double) _pixmap.height();

		// if pixmap wasnt set leave 
	if( ( w == 0 ) || ( h == 0 ) ) return; 
	
		// create manip item if they are not presented and add them to scene
	if( !_pRoi )
	{
		_pRoi = new GRoi();
		_pRoi->setZValue( 1.0 );
		this->addItem( _pRoi );
	}
	if( !_pStartMarker )
	{
		_pStartMarker = new GMarker( Qt::darkMagenta );
		_pStartMarker->setToolTip( tr( "Release marker. Move around the scene." ) );
		_pStartMarker->setZValue( 2.0 );
		this->addItem( _pStartMarker );
	}
	if( !_pEndMarker )
	{
		_pEndMarker = new GMarker( Qt::darkCyan );
		_pEndMarker->setToolTip( tr( "Shut marker. Move around the scene." ) );
		_pEndMarker->setZValue( 2.0 );
		this->addItem( _pEndMarker );
	}
	
	if( !_pRoi || !_pStartMarker || !_pEndMarker ) return;
	
		// set Roi
	QPolygonF nodes;
	nodes << QPointF( w*0.1, h*0.1 ) << QPointF( w - w*0.1, h*0.1 )
			<< QPointF( w - w*0.1, h - h*0.1 ) << QPointF( w*0.1, h - h*0.1 );
	_pRoi->createNodes( nodes );
	
		// set default hooks position
	_pStartMarker->setHooks( QPointF( w*0.15, h*0.15 ), QPointF( w - w*0.15, h*0.15 ) );
	_pEndMarker->setHooks( QPointF( w - w*0.15, h - h*0.15 ), QPointF( w*0.15, h - h*0.15 ) );

		// if user sets tools visibility, manage his will 
	if( _userVisibility ) showTools( _visible );
}
// ---------------------------------------------------------------------------


// -------------------- GRoiEditor::setRoiNodes() ----------------------------
void GRoiEditor::setRoiNodes( const QPolygonF & nodes )
{
		// if Roi isn't present create one
	if( !_pRoi )
	{
		_pRoi = new GRoi();
		_pRoi->setZValue( 1.0 );
		this->addItem( _pRoi );
	}
	if( _pRoi ) _pRoi->createNodes( nodes );
}
// ---------------------------------------------------------------------------


// -------------------- GRoiEditor::setStartMarkerHooks() --------------------
void GRoiEditor::setStartMarkerHooks( const QPointF & pos1,
									  const QPointF & pos2 )
{
		// if start marker isn't present create one
	if( !_pStartMarker )
	{
		_pStartMarker = new GMarker( Qt::darkGreen );
		_pStartMarker->setZValue( 2.0 );
		this->addItem( _pStartMarker );
	}
	if( _pStartMarker ) _pStartMarker->setHooks( pos1, pos2 );
}
// ---------------------------------------------------------------------------


// ------------------- GRoiEditor::setEndMarkerHook() ------------------------
void GRoiEditor::setEndMarkerHooks( const QPointF & pos1,
									const QPointF & pos2 )
{
        // if end marker isn't present create one
    if( !_pEndMarker )
    {
        _pEndMarker = new GMarker( Qt::darkRed );
        _pEndMarker->setZValue( 2.0 );
        this->addItem( _pEndMarker );
    }
    if( _pEndMarker ) _pEndMarker->setHooks( pos1, pos2 );
}
// ---------------------------------------------------------------------------


// -------------------- GRoiEditor::markersImage() ---------------------------
pimage_t GRoiEditor::markersImage()const
{
	if( !_pStartMarker | !_pEndMarker ) return create_image( 0, 0 );
	
		// create regions image in size of loaded image (_pixmap)
	QImage regionsImage( _pixmap.size(), QImage::Format_ARGB32_Premultiplied );
	
		// create painter
	QPainter painter( &regionsImage );
	painter.setPen( Qt::NoPen );
		// fill regionsImage transparently
	painter.setCompositionMode( QPainter::CompositionMode_Source );
	painter.fillRect( regionsImage.rect(), Qt::transparent );
		// draw start marker region
	painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
	painter.setBrush( Qt::red );
	painter.drawPath( _pStartMarker->markerRegion() );
		// set XOR composition mode and paint end marker region
	painter.setCompositionMode( QPainter::CompositionMode_Xor );
	painter.setBrush( Qt::blue );
	painter.drawPath(  _pEndMarker->markerRegion() );
		// paint background
	painter.setCompositionMode( QPainter::CompositionMode_DestinationOver );
	painter.fillRect( regionsImage.rect(), Qt::green );
	painter.end();
	
		// create image
	pimage_t pimage = create_image( regionsImage.width(), regionsImage.height() );
	
	// start marker region is red colored - is changed into indexed 0
	// central region is green colored - is changed into indexed 1
	// end marker region is blue colored - is changed into indexed 2
	// other colors are changed into indexed 3
	
		// copy data
	Q_ASSERT( pimage );
	for( int y = 0; y < pimage->height; y++ )
	{
		for( int x = 0 ; x < pimage->width; x++ )
		{
			if( regionsImage.pixel( x, y ) == qRgb( 255, 0, 0 ) )
				image_pixel( pimage, x, y ) = 0;
			else if( regionsImage.pixel( x, y ) == qRgb( 0, 255, 0 ) )
				image_pixel( pimage, x, y ) = 1;
			else if( regionsImage.pixel( x, y ) == qRgb( 0, 0, 255 ) )
				image_pixel( pimage, x, y ) = 2;
			else
				image_pixel( pimage, x, y ) = 3;
		}
	}
	
	return pimage;
}
// ---------------------------------------------------------------------------


// ---------------------- GRoiEditor::roiImage() -----------------------------
pimage_t GRoiEditor::roiImage()const
{
	if( !_pRoi ) return create_image( 0, 0 );
	
	
		// create regions image in size of loaded image (_pixmap)
	QImage regionsImage( _pixmap.size(), QImage::Format_RGB32 );
	
		// create painter
	QPainter painter( &regionsImage );
	painter.setPen( Qt::NoPen );
		// fill regionsImage with red (indexed 0),
		// at default hole image is outer region
	painter.fillRect( regionsImage.rect(), Qt::red );
		// draw roi region
	painter.setBrush( Qt::green );
	painter.drawPath( _pRoi->roiRegion() );
	painter.end();
	
		// create image
	pimage_t pimage = create_image( regionsImage.width(), regionsImage.height() );
	
	// region not interested is red colored - is changed into indexed 0
	// central region is green colored - is changed into indexed 1
	// other colors are changed into indexed 2
	
		// copy data
	Q_ASSERT( pimage );
	for( int y = 0; y < pimage->height; y++ )
	{
		for( int x = 0 ; x < pimage->width; x++ )
		{
			if( regionsImage.pixel( x, y ) == qRgb( 255, 0, 0 ) )
				image_pixel( pimage, x, y ) = 0;
			else if( regionsImage.pixel( x, y ) == qRgb( 0, 255, 0 ) )
				image_pixel( pimage, x, y ) = 1;
			else
				image_pixel( pimage, x, y ) = 2;
		}
	}
	
	return pimage;
}
// ---------------------------------------------------------------------------


// ----------------------- GRoiEditor::roiNodes() ----------------------------
QPolygonF GRoiEditor::roiNodes()const
{
	if( !_pRoi ) return QPolygonF();
	return _pRoi->nodes();
}
// ---------------------------------------------------------------------------


// ----------------------- GRoiEditor::startMarkerHooks() --------------------
QPolygonF GRoiEditor::startMarkerHooks()const
{
	if( !_pStartMarker ) return QPolygonF();
	return _pStartMarker->hooks();
}
// ---------------------------------------------------------------------------


// ---------------------- GRoiEditor::endMarkerHooks() -----------------------
QPolygonF GRoiEditor::endMarkerHooks()const
{
	if( !_pEndMarker ) return QPolygonF();
	return _pEndMarker->hooks();
}
// ---------------------------------------------------------------------------




// eof
